package ldh.text.controller.segment;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import ldh.text.service.CursorDataService;
import ldh.text.util.RegexUtil;
import ldh.text.util.ThreadPoolUtil;
import org.fxmisc.richtext.GenericStyledArea;
import org.fxmisc.richtext.StyleClassedTextArea;
import org.fxmisc.richtext.model.Paragraph;
import org.reactfx.collection.LiveList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.util.Collection;

public class DataControlPaneController {

    private static final Logger LOGGER = LoggerFactory.getLogger(DataControlPaneController.class);

    @FXML private Pane dataControlPane;
    @FXML private TextField positionValue;
    @FXML private Label fileSizeLabel;

    private int cacheSize;
    private int moreNextSize;
    private CursorDataService<ByteBuffer> dataService;
    private GenericStyledArea textArea;

    public void setDataService(CursorDataService cacheDataService, int cacheSize, int moreNextSize) {
        this.dataService = cacheDataService;
        this.cacheSize = cacheSize;
        this.moreNextSize = moreNextSize;
    }

    public void setDataSize(long fileSize) {
        positionValue.setText("0");
        fileSizeLabel.setText(fileSize + "(文件大小)");
    }

    public void setTextArea(StyleClassedTextArea textArea) {
        this.textArea = textArea;
    }

    @FXML
    private void firstData(ActionEvent actionEvent) {
        if (dataService.getStartPosition() == 0) return;
        disablePaginationPane();
        clearFind();
        ThreadPoolUtil.submit(()->{
            try {
                ByteBuffer data = dataService.loadData(0, cacheSize);
                if (data.limit() < 1) return;
                String content = new String(data.array(), 0, data.limit(), "utf8");
                Platform.runLater(()->{
                    try {
                        textArea.clear();
                        textArea.insertText(0, content);
                        positionValue.setText(dataService.getStartPosition() + "");
                    } finally {
                        ablePaginationPane();
                    }
                });
            } catch (Exception e) {
                LOGGER.error("open file error", e);
            }
        });
    }

    @FXML
    private void nextMoreData(ActionEvent actionEvent) {
        Button b = new Button();
        disablePaginationPane();
        clearFind();
        ThreadPoolUtil.submit(()->{
            try {
                ByteBuffer data = dataService.loadNextData(moreNextSize);
                if (data.array().length == 0) {
                    ablePaginationPane();
                    return;
                }
                String content = new String(data.array(), 0, data.limit(), "utf8");
                int length = textArea.getText().length();
                final int newLength = length + content.length();
                Platform.runLater(()->{
                    try {
                        int selectStart = textArea.getSelection().getStart();
                        int selectEnd = textArea.getSelection().getEnd();
                        LOGGER.info("select length: {}", selectEnd - selectStart);
                        int newLength2 = newLength;
                        if (length > moreNextSize) {
                            textArea.deleteText(0, moreNextSize);
                            newLength2 -= moreNextSize;
//                            textArea.replaceText(0, moreNextSize, "");
                            selectStart -= moreNextSize;
                            selectEnd -= moreNextSize;
                        }
                        textArea.appendText(content);

                        positionValue.setText(dataService.getStartPosition() + "");
                        if (selectStart < 0) selectStart = 0;
                        if (selectEnd < 0) return;
                        if (selectEnd < 1 || selectStart == selectEnd) return;
                        if (selectEnd > newLength2) selectEnd = newLength2;
                        LOGGER.info("select length: {}", selectEnd - selectStart);
                        textArea.selectRange(selectStart, selectEnd);
                    } finally {
                        ablePaginationPane();
                    }
                });
            } catch (Exception e) {
                LOGGER.error("open file error", e);
            }
        });
    }

    @FXML
    private void positionData(ActionEvent actionEvent) {
        disablePaginationPane();
        clearFind();
        ThreadPoolUtil.submit(()->{
            try {
                int position = Integer.parseInt(positionValue.getText());
                ByteBuffer data = dataService.loadData(position, cacheSize);
                if (data.limit() < 1) return;
                String content = new String(data.array(), 0, data.limit(), "utf8");
                Platform.runLater(()->{
                    try {
                        textArea.clear();
                        textArea.insertText(0, content);
                    } finally {
                        ablePaginationPane();
                    }
                });
            } catch (Exception e) {
                LOGGER.error("open file error", e);
            }
        });
    }

    @FXML
    private void bottomData(ActionEvent actionEvent) {
        disablePaginationPane();
        clearFind();
        ThreadPoolUtil.submit(()->{
            try {
                long position = dataService.dataSize() - cacheSize;
                ByteBuffer data = dataService.loadData(position, cacheSize);
                if (data.limit() < 1) return;
                String content = new String(data.array(), 0, data.limit(), "utf8");
                Platform.runLater(()->{
                    try {
                        textArea.clear();
                        textArea.insertText(0, content);
                        positionValue.setText(dataService.getStartPosition() + "");
                    } finally {
                        ablePaginationPane();
                    }
                });
            } catch (Exception e) {
                LOGGER.error("open file error", e);
            }
        });
    }

    /**
     * 向上加载
     * @param actionEvent
     */
    @FXML
    private void preNextData(ActionEvent actionEvent) {
        disablePaginationPane();
        clearFind();
        ThreadPoolUtil.submit(()->{
            try {
                ByteBuffer data = dataService.loadPreData(moreNextSize);
                if (data.array().length == 0) {
                    ablePaginationPane();
                    return;
                }
                String content = new String(data.array(), 0, data.limit(), "utf8");
                int lineNum = RegexUtil.totalFind(content, "\r|\n|\r\n|\n\r");
                int position = textArea.getText().length() - moreNextSize;

                int length = content.length();
                int currentParagraph = textArea.getCurrentParagraph();
                Platform.runLater(()->{
                    try {
                        int selectStart = textArea.getSelection().getStart();
                        int selectEnd = textArea.getSelection().getEnd();
                        if (position > 0) {
                            textArea.deleteText(position, position + moreNextSize);
//                            textArea.replaceText(position, position + moreNextSize, "");
                            selectStart += length;
                            selectEnd += length;
                        }
                        textArea.insertText(0, content);
                        int newCurrentParagraph = currentParagraph + lineNum;
                        if (newCurrentParagraph > textArea.getParagraphs().size()) {
                            newCurrentParagraph = textArea.getParagraphs().size();
                        }
                        textArea.showParagraphInViewport(newCurrentParagraph);
                        positionValue.setText(dataService.getStartPosition() + "");

                        int newLength = textArea.getText().length();
                        if (selectStart > newLength) return;
                        if (selectEnd > newLength) selectEnd = newLength;
                        if (selectEnd == selectStart) return;
                        textArea.selectRange(selectStart, selectEnd);
                    } finally {
                        ablePaginationPane();
                    }
                });
            } catch (Exception e) {
                LOGGER.error("open file error", e);
            }
        });
    }

    private void disablePaginationPane() {
        dataControlPane.setDisable(true);
    }

    private void ablePaginationPane() {
        dataControlPane.setDisable(false);
    }

    private void clearFind() {
//        searchRangeList.clear();
    }

}
